#ifndef _network_NetworkController_hpp_
#define _network_NetworkController_hpp_

/** \file NetworkController.hpp
 *  \author Micha Begert
 *  \created  $Sa 22 Sep 15:07:00 pm CEST 2007 $
 *  \modified $Sa 19 Jan 09:11:41 pm CET 2008 schwadri@Macintosh.local$
 */

#include "Client.hpp"
#include "../core/bitstream.hpp"
#include <boost/signal.hpp>
#include <boost/signals/slot.hpp>
#include <boost/signals/trackable.hpp>
#include <boost/signals/connection.hpp>
#include <boost/visit_each.hpp>
#include <boost/last_value.hpp>

namespace network {

    /** \brief The NetworkController
     *
     *  Controlls all network related activities
     */
    class NetworkController :   private boost::noncopyable
    {
    public:

        static NetworkController& getNetworkController();
                                 ~NetworkController();


        bool Host(const Address& a, int max_clients);
        bool Connect(const Address& a);


        void Shutdown();

        void Kick(Client::Id);
        void Ban(Client::Id);

        void ProcessMessages();

        void Send(/*const*/ core::bitstream& stream, receiver_mask receivers, ReliabilityLevel rlvl);
        void Send(/*const*/ core::bitstream& stream, Client::Id cid, ReliabilityLevel rlvl);


        // Getter / Setter
        /** \brief true if its a server.*/
        bool IsServer() const              { return m_isServer; }

        //Signals
        mutable boost::signal<void (Client::Id)>                    ConnectedSignal;
        mutable boost::signal<void (DisconnectReason)>              DisonnectedSignal;
        mutable boost::signal<void (Client::Id)>                    ClientConnectedSignal;
        mutable boost::signal<void (Client::Id, DisconnectReason)>  ClientDisconnectedSignal;
        mutable boost::signal<void (core::bitstream&, Client::Id)>  PacketSignal;


    private:
        void Send(/*const*/ core::bitstream& stream, Address& adress, ReliabilityLevel rlvl);
        NetworkController();

        static const int            MAX_CLIENTS = NETWORK_RECEIVER_MASK_SIZE;
        static const int            PACKAGE_THRESHOLD = 100;

        bool                        m_isServer;
        int                         serverPort;

    };
} // namespace network

#endif // _network_NetworkController_hpp_
